package cn.ray.springframework.beans.factory.support;


import cn.ray.springframework.beans.BeansException;
import cn.ray.springframework.beans.factory.FactoryBean;
import cn.ray.springframework.beans.factory.config.BeanDefinition;
import cn.ray.springframework.beans.factory.config.BeanPostProcessor;
import cn.ray.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.ClassUtils;


import java.util.ArrayList;
import java.util.List;

//继承defaultSingletonBeanRegistery，具备使用单例注册类功能
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    private final List<BeanPostProcessor> beanPostProcessors=new ArrayList<BeanPostProcessor>();

    private ClassLoader beanClassLoader= ClassUtils.getDefaultClassLoader();
    public ClassLoader getBeanClassLoader(){
        return this.beanClassLoader;
    }

    //对单例Bean对象的获取
    //模板方法的体现，抽象类定义getBean流程，具体如何创建由子类实现
    @Override
    public Object getBean(String name) throws BeansException {
        return dogetBean(name,null);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return dogetBean(name,args);
    }

    //抽离创建bean逻辑
    protected <T> T dogetBean(final String name, final Object[]args){
        Object sharedInstance=getSingleton(name);
        if(sharedInstance!=null){
            //如果是FactoryBean类，则需要调用factoryBean的getObject方法（专业的事交给专业的人去做）
            return (T) getObjectForBeanInstance(sharedInstance,name);
        }
        BeanDefinition beanDefinition=getBeanDefinition(name);
        return (T) createBean(name,beanDefinition,args);
    }

    private Object getObjectForBeanInstance(Object sharedInstance, String name) {
        if(!(sharedInstance instanceof FactoryBean)){
            return sharedInstance;
        }

        //先尝试从缓存中获取
        Object object=getCachedObjectForFactoryBean(name);

        if(object==null){
            FactoryBean<?>factoryBean= (FactoryBean<?>) sharedInstance;
            object=getObjectFromFactoryBean(factoryBean,name);
        }

        return object;
    }

    //获取bean的定义和bean创建交由子类完成
    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

    protected abstract Object createBean(String name, BeanDefinition beanDefinition, Object[] args) throws BeansException;

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }

    public List<BeanPostProcessor>getBeanPostProcessors(){
        return this.beanPostProcessors;
    }
}
